//
// Created by lenovo on 2024/1/12.
//
#include <exception>
#include "Lexer.h"
#include <stack>
Evaluable* Lexer::root() {
    this->check();
    this->Build();
    if (this->tokens.size() > 1){
        throw std::logic_error("UnCompleted Syntax Tree Building Process!");
    }
    else if (this->tokens.empty()){
        return nullptr;
    }
    else
        return this->tokens[0]->base;
}

void Lexer::check() {
    std::stack<bool> brackets ;
    for (auto token : tokens){
        if (token->type == token::LBRACKET){
            brackets.push(1);
        }
        if (token->type == token::RBRACKET){
            if (not brackets.empty())
                brackets.pop();
            else
                throw std::logic_error("A single ')' is not allowed!");
        }
    }
    if (not brackets.empty()){
        throw std::logic_error("Unclosed bracket !");
    }
}

#include <iostream>
#include <utility>
using namespace std ;

class TreeBuilder{
public:
    TreeBuilder(
            std::vector<token*> *tks ,
            std::set<std::string> opts
    )
            : tokens(tks) , identified_opts(std::move(opts))
    {} ;
    vector<token*>* reuslt() ;

protected:
    std::set<std::string> identified_opts ;
    void Build() ;
    std::vector<token*> *tokens;
    bool _done {false};
};

void Lexer::Build() {
    this->negationOptimize();
    this->funcExtract();
    this->bracketConvert();

    for (auto & it : *this->priority)
    {
        TreeBuilder tb(&(this->tokens) , it) ;
        tb.reuslt();
    }

}


void Lexer::bracketConvert() {
    int i = 0 ;
    //括号处理
    while (i < this->tokens.size()){
        auto cur = this->tokens[i];

        if (cur->type == token::Type::LBRACKET){
            std::stack<bool> brackets ;
            brackets.push(1);

            std::vector<token*> subTokens ;

            int j = i + 1;

            while (true){
                if (this->tokens[j]->type == token::LBRACKET){
                    brackets.push(1);
                }else if (this->tokens[j]->type == token::RBRACKET){
                    brackets.pop();
                    if (brackets.empty())
                        break;
                }
                subTokens.push_back(this->tokens[j]);
//                cout << "Sub Token Size is : "<<subTokens.size() << endl ;
                j ++ ;
            }

//            cout << i << ' ' << j << endl ;
            this->tokens.erase(
                    this->tokens.begin() + i ,
                    this->tokens.begin() + j + 1
            );
//            cout << endl << endl ;

            if (not subTokens.empty()){
                Lexer subLexer(subTokens , this->_identified_funcs , this->priority);

                this->tokens.insert(
                        this->tokens.begin() + i ,
                        new token(
                                token::Type::NUMBER,
                                subLexer.root()
                        )
                );
            }
        }

        i ++ ;
    }
}




//vector<token *> *TreeBuilder::reuslt() {
//    if (not _done){
//        this->Build();
//    }
//    _done = true ;
//    return tokens;
//}

void TreeBuilder::Build() {
    int i = 0 ;
    while (i < this->tokens->size()){
        auto cur = this->tokens->at(i);
        auto type = cur->type;
        if (type == token::Type::OPERATOR){
            if (
                    this->identified_opts.find(
                            ((Operator*)cur->base)->OptType)
                    !=
                    this->identified_opts.end())
            {
                //能识别当前符号
                auto* node = (Operator*)cur->base;
                node->pre =  this->tokens->at(i - 1)->base;
                node->post = this->tokens->at(i + 1)->base;

                delete cur ;
                this->tokens->erase(
                        this->tokens->begin() + ( i - 1 ),
                        this->tokens->begin() + ( i + 1 ) + 1
                        );
                this->tokens->insert(
                        this->tokens->begin() + i - 1 ,
                        new token(
                                token::Type::NUMBER,
                                node
                                )
                        );
                i -- ;
            }
        }

        i ++ ;
    }
}

vector<token *> *TreeBuilder::reuslt() {
    if (not _done){
        this->Build();
    }
    _done = true ;
    return this->tokens ;
}
